﻿namespace FlexPlatform.BusinessLogic.Controllers
{
    using FlexPlatform.Common.Configuration;
    using FlexPlatform.Shared.Presenters;
    using FlexPlatform.Shared.DataModel;
    using FlexPlatform.Shared.Events;
    using System.ComponentModel;
    using System.Collections.Generic;
using System.Collections.ObjectModel;
    using FlexPlatform.Shared.Validation;

    public class PropertyValidationController
    {
        #region Private fields & Constructor(s)

        /// <summary>
        /// The validation configuration for controlled property.
        /// </summary>
        private IPropertyValidationConfiguration clsConfiguration;

        /// <summary>
        /// The controlled data entity.
        /// </summary>
        private IDataEntity clsDataEntity;

        /// <summary>
        /// Creates a controller for property validation functionaliy.
        /// </summary>
        /// <param name="configuration">The validation configuration for controlled property.</param>
        /// <param name="dataEntity">The controlled data entity.</param>
        public PropertyValidationController(IPropertyValidationConfiguration configuration, IDataEntity dataEntity)
        {
            clsConfiguration = configuration;
            clsDataEntity = dataEntity;

            // attach to the relevant events of the controlled DataEntity:
            this.clsDataEntity.BeforePropertyChange += OnBeforePropertyChange;
        }

        #endregion

        #region Events handling (from DataEntity)

        /// <summary>
        /// Handles the DataEntity.BeforePropertyChange event.
        /// Validates the property using the logic in the configuration element.
        /// </summary>
        /// <param name="eventArgs">The extra data handled event provides.</param>
        /// <param name="sender">The sender of this event.</param>
        private void OnBeforePropertyChange(object sender, BeforeProperyChangeEventArgs eventArgs)
        {
            Collection<IValidationResult> validationResults = new Collection<IValidationResult>();

            // Validate this new 'candidate' value, over each configured validation rule
            foreach (var rule in clsConfiguration.ValidationRules)
            {
                var validationResult = rule.Validate(eventArgs.ProposedValue);
                
                // request to cancel the value update if validation failed
                if (!validationResult.ValidationPassed)
                {
                    eventArgs.RequestToCancel();
                }

                // add the current result to the list 
                validationResults.Add(validationResult);
            }

            // store the new validation results inside the presenter:
            this.clsDataEntity.Presenter.ValidationResults = validationResults;      
        }

        #endregion
    }
}
